# -*- coding: utf-8 -*-
"""
基础UI组件类
定义所有UI组件的基本属性和方法
"""

import pygame
from abc import ABC, abstractmethod
from typing import Tuple, Optional, Callable


class BaseComponent(ABC):
    """
    UI组件基类
    所有UI组件都应该继承此类
    """
    
    def __init__(self, x: int, y: int, width: int, height: int):
        """
        初始化基础组件
        
        Args:
            x (int): 组件X坐标
            y (int): 组件Y坐标
            width (int): 组件宽度
            height (int): 组件高度
        """
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.visible = True
        self.enabled = True
        self.focused = False
        self.hovered = False
        
        # 事件回调函数
        self.on_click: Optional[Callable] = None
        self.on_hover: Optional[Callable] = None
        self.on_focus: Optional[Callable] = None
        self.on_blur: Optional[Callable] = None
        
        # 组件矩形区域
        self.rect = pygame.Rect(x, y, width, height)
    
    @property
    def position(self) -> Tuple[int, int]:
        """获取组件位置"""
        return (self.x, self.y)
    
    @position.setter
    def position(self, pos: Tuple[int, int]):
        """设置组件位置"""
        self.x, self.y = pos
        self.rect.x, self.rect.y = pos
    
    @property
    def size(self) -> Tuple[int, int]:
        """获取组件大小"""
        return (self.width, self.height)
    
    @size.setter
    def size(self, size: Tuple[int, int]):
        """设置组件大小"""
        self.width, self.height = size
        self.rect.width, self.rect.height = size
    
    def set_position(self, x: int, y: int):
        """设置组件位置"""
        self.position = (x, y)
    
    def set_size(self, width: int, height: int):
        """设置组件大小"""
        self.size = (width, height)
    
    def move(self, dx: int, dy: int):
        """移动组件"""
        self.set_position(self.x + dx, self.y + dy)
    
    def resize(self, dw: int, dh: int):
        """调整组件大小"""
        self.set_size(self.width + dw, self.height + dh)
    
    def contains_point(self, x: int, y: int) -> bool:
        """检查点是否在组件内"""
        return self.rect.collidepoint(x, y)
    
    def set_visible(self, visible: bool):
        """设置组件可见性"""
        self.visible = visible
    
    def set_enabled(self, enabled: bool):
        """设置组件启用状态"""
        self.enabled = enabled
    
    def set_focus(self, focused: bool):
        """设置组件焦点状态"""
        if self.focused != focused:
            self.focused = focused
            if focused and self.on_focus:
                self.on_focus()
            elif not focused and self.on_blur:
                self.on_blur()
    
    def set_hover(self, hovered: bool):
        """设置组件悬停状态"""
        if self.hovered != hovered:
            self.hovered = hovered
            if hovered and self.on_hover:
                self.on_hover()
    
    @abstractmethod
    def draw(self, surface: pygame.Surface):
        """绘制组件（抽象方法，子类必须实现）"""
        pass
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件
        
        Args:
            event: Pygame事件对象
            
        Returns:
            bool: 如果事件被处理返回True，否则返回False
        """
        if not self.visible or not self.enabled:
            return False
        
        # 处理鼠标事件
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # 左键点击
                if self.contains_point(event.pos[0], event.pos[1]):
                    self.set_focus(True)
                    if self.on_click:
                        self.on_click()
                    return True
                else:
                    self.set_focus(False)
        
        elif event.type == pygame.MOUSEMOTION:
            # 检查鼠标悬停
            is_hovering = self.contains_point(event.pos[0], event.pos[1])
            self.set_hover(is_hovering)
        
        return False
    
    def update(self, dt: float):
        """更新组件状态
        
        Args:
            dt (float): 时间增量（秒）
        """
        pass
    
    def __str__(self) -> str:
        """字符串表示"""
        return f"{self.__class__.__name__}(x={self.x}, y={self.y}, w={self.width}, h={self.height})"
    
    def __repr__(self) -> str:
        """详细字符串表示"""
        return self.__str__()


class ComponentManager:
    """
    组件管理器
    管理多个UI组件的绘制和事件处理
    """
    
    def __init__(self):
        self.components = {}  # 改为字典以支持命名组件
        self.component_list = []  # 保持绘制顺序
        self.focused_component: Optional[BaseComponent] = None
    
    def add_component(self, name: str, component: BaseComponent):
        """添加命名组件"""
        if name in self.components:
            # 如果组件已存在，先移除旧的
            self.remove_component(name)
        
        self.components[name] = component
        self.component_list.append(component)
    
    def remove_component(self, name_or_component):
        """移除组件（支持按名称或组件对象移除）"""
        if isinstance(name_or_component, str):
            # 按名称移除
            if name_or_component in self.components:
                component = self.components[name_or_component]
                del self.components[name_or_component]
                if component in self.component_list:
                    self.component_list.remove(component)
                if self.focused_component == component:
                    self.focused_component = None
        else:
            # 按组件对象移除
            component = name_or_component
            # 找到组件名称
            name_to_remove = None
            for name, comp in self.components.items():
                if comp == component:
                    name_to_remove = name
                    break
            
            if name_to_remove:
                del self.components[name_to_remove]
            if component in self.component_list:
                self.component_list.remove(component)
            if self.focused_component == component:
                self.focused_component = None
    
    def get_component(self, name: str) -> Optional[BaseComponent]:
        """根据名称获取组件"""
        return self.components.get(name)
    
    def clear_components(self):
        """清空所有组件"""
        self.components.clear()
        self.component_list.clear()
        self.focused_component = None
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件，按Z轴顺序（后添加的组件优先）"""
        # 反向遍历，后添加的组件优先处理事件
        for component in reversed(self.component_list):
            if component.handle_event(event):
                # 更新焦点组件
                if component.focused and self.focused_component != component:
                    if self.focused_component:
                        self.focused_component.set_focus(False)
                    self.focused_component = component
                return True
        return False
    
    def update(self, dt: float):
        """更新所有组件"""
        for component in self.component_list:
            component.update(dt)
    
    def draw(self, surface: pygame.Surface):
        """绘制所有可见组件"""
        for component in self.component_list:
            if component.visible:
                component.draw(surface)
    
    def get_component_at(self, x: int, y: int) -> Optional[BaseComponent]:
        """获取指定位置的组件（最上层的）"""
        for component in reversed(self.component_list):
            if component.visible and component.contains_point(x, y):
                return component
        return None
    
    def get_components_by_type(self, component_type: type) -> list:
        """根据类型获取组件列表"""
        return [comp for comp in self.component_list if isinstance(comp, component_type)]
    
    def get_component_names(self) -> list:
        """获取所有组件名称列表"""
        return list(self.components.keys())
    
    def has_component(self, name: str) -> bool:
        """检查是否存在指定名称的组件"""
        return name in self.components